<?php

namespace App\Http\Controllers\V1;

use App\Models\User;
use App\Support\Code;
use App\Models\Record;
use App\Models\Packet;
use App\Models\Address;
use App\Models\Version;
use App\Support\Config;
use App\Support\Currency;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Overtrue\EasySms\EasySms;
use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Storage;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use App\Http\Requests\AuthenticationRequest;
use App\Http\Requests\VerificationCodeRequest;


class UserController extends ApiController
{
    public function show()
    {
        $user = $this->getUser();

        return $this->success(new UserResource($user));
    }

    // 助记词验证
    public function verify(Request $request)
    {
        $user = $this->getUser();
        if ($user->status !== User::STATUS_UNVERIFIED) {
            return $this->fail(Code::PARAMETER_ERROR, '已验证');
        }

        if ($request->mnemonic_word !== $user->mnemonic_word) {
            return $this->fail(Code::PARAMETER_ERROR, '助记词错误');
        }

        $user->status = User::STATUS_NOT_ACTIVE;

        // 生成 ETH 收款地址
        $this->generateEthAddress();

        $user->save();

        return $this->success();
    }

    // 获取乱序助记词
    public function bips()
    {
        $mnemonics = $this->getUser()->mnemonic_word;

        shuffle($mnemonics);
        return $this->success($mnemonics);
    }

    /**
     * 生成 eth 收款地址
     */
    private function generateEthAddress()
    {
        $client = get_eth_client();

        $res = $client->post('/newEthAccount');
        $data = json_decode($res->getBody(), true)['data'];

        Address::create([
            'currency' => Currency::ETH,
            'address' => $data['address'],
            'user_id' => $this->getUser()->id
        ]);
    }

    public function update(Request $request)
    {
        if ($request->has('password')) {
            return $this->updatePassword($request);
        }

        if ($request->has('pay_passwd')) {
            return $this->updatePayPasswd($request);
        }

        $input = Arr::only($request->all(), [
            'nickname',
            'avatar_big',
            'avatar_small',
        ]);

        $user = $this->getUser();

        foreach ($input as $key => $value) {
            $user->{$key} = $value;
        }
        $user->save();

        return $this->success();
    }

    /**
     * 更新支付密码
     *
     * @param  Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    private function updatePayPasswd(Request $request)
    {
        $user = $this->getUser();

        if ($request->mnemonic_word !== $user->mnemonic_word) {
            return $this->fail(Code::PARAMETER_ERROR, '助记词错误');
        }

        if ($request->pay_passwd !== $request->confirm_passwd) {
            return $this->fail(Code::PARAMETER_ERROR, '密码前后不一致');
        }

        $user->pay_passwd = $request->pay_passwd;
        $user->save();

        return $this->success();
    }

    private function updatePassword(Request $request)
    {
        $user = $this->getUser();

        if ($request->mnemonic_word !== $user->mnemonic_word) {
            return $this->fail(Code::PARAMETER_ERROR, '助记词错误');
        }

        $user->password = $request->password;
        $user->save();

        return $this->success();
    }

    public function assets()
    {
        $user = $this->getUser();
        return $this->success([
            'vrt' => $user->vrt,
            'yec' => $user->yec,
            'vrts' => $user->vrts,
            'yecs' => $user->yecs,
            'eth' => (string) number_format($user->eth - $user->eth_freeze, 8)
        ]);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ConfigNotSetException
     */
    public function vrt()
    {
        $user = $this->getUser();
        $config = Config::getMultipleRatios();
        $rmb = $config['vrt'] ?? '0';
        $data = [
            'balance' => $user->vrt,
            'freeze' => (string) number_format('0', 8)
        ];
        $data['rmb'] = number_format($user->vrt * $rmb, 2);
        $data['vrts'] = number_format($user->vrt * $rmb, 2);

        $data['records'] = Record::whereCurrency(Currency::VRT)
            ->whereUserId($user->id)->orderByDesc('created_at')->paginate()->items();

        return $this->success($data);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ConfigNotSetException
     */
    public function vrts()
    {
        $user = $this->getUser();
        $config = Config::getMultipleRatios();
        $rmb = $config['vrts'] ?? '0';
        $data = [
            'balance' => $user->vrts,
            'freeze' => $user->vrts_freeze
        ];
        $data['rmb'] = number_format($user->vrts * $rmb, 2);
        $data['vrts'] = number_format($user->vrts * $rmb, 2);

        $data['records'] = Record::whereCurrency(Currency::VRTS)
            ->whereUserId($user->id)->orderByDesc('created_at')->paginate()->items();

        return $this->success($data);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ConfigNotSetException
     */
    public function yec()
    {
        $user = $this->getUser();
        $config = Config::getMultipleRatios();
        $rmb = $config['yec'] ?? '0';
        $data = [
            'balance' => $user->yec,
            'freeze' => $user->yec_freeze
        ];
        $data['rmb'] = number_format($user->yec * $rmb, 2);
        $data['vrts'] = number_format($user->yec * $rmb, 2);

        $data['records'] = Record::whereCurrency(Currency::YEC)
            ->whereUserId($user->id)->orderByDesc('created_at')->paginate()->items();

        return $this->success($data);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * @throws \App\Exceptions\ConfigNotSetException
     */
    public function eth()
    {
        $user = $this->getUser();
        $config = Config::getMultipleRatios();
        $rmb = $config['eth'] ?? '0';
        $data = [
            'freeze' => $user->eth_freeze,
            'balance' => (string) number_format($user->eth - $user->eth_freeze, 8)
        ];
        $data['rmb'] = number_format($user->eth * $rmb, 2);
        $data['vrts'] = number_format($user->eth * $rmb, 2);

        $data['records'] = Record::whereCurrency(Currency::ETH)
            ->whereUserId($user->id)->orderByDesc('created_at')->paginate()->items();

        return $this->success($data);
    }

    /**
     * 我的 YECS
     */
    public function yecs()
    {
        $user = $this->getUser();
        $data = ['balance' => $user->yecs];

        $data['released'] = Packet::whereUserId($user->id)
            ->where('created_at', '>', now()->subDay()->toDateString())
            ->where('created_at', '<', now()->toDateString())->sum('value');

        $data['released'] = number_format($data['released'], 2);

        $data['records'] = Record::whereCurrency(Currency::YECS)
            ->whereUserId($user->id)->orderByDesc('created_at')->paginate()->items();

        return $this->success($data);
    }

    public function share(int $id)
    {
        $user = User::find($id);
        $children = $user->childrens()->select('avatar_small', 'name')->get();
        if (count($children)) {
            foreach ($children as $k=>$v) {
                if (!$v->avatar_small) {
                    $children[$k]['avatar_small'] = storage_url('/avatars/default.png');
                }
            }
        }
        $file = 'qrcodes/' . md5($user->invitation_code) . '.png';

        if (!Storage::disk('public')->exists($file)) {
            Storage::disk('public')->put(
                $file,
                QrCode::format('png')->size(224)
                    ->generate(url('/api/v1/pc/register?code=' . $user->invitation_code))
            );
        }

        return $this->success([
            'count1' => $children->count(),
            'count2' => 0, // todo 间推数量
            'qrcode' => storage_url($file),
            'children' => $children->toArray(),
            'invitation_code' => $user->invitation_code,
            'download_url' => url('/api/v1/users/down'),
        ]);
    }

    public function getShare(Request $request)
    {
        $url = env('APP_URL');
        $id = $request->input('id');
        if (!$id) {
            return $this->fail(Code::PARAMETER_ERROR, '参数错误');
        }
        return view('share.share', compact('id', 'url'));
    }

    public function download(Request $request)
    {
       $version = Version::where(['type'=>0,'force'=>1])
            ->orderByDesc('created_at')->first(['id','version','link']);
        if (is_null($version)) {
            $file = 'http://ssr.ubpay.vip/storage/versions/1.1.0.apk';
        } else {
            $file = $version->link;
        }
        $file_qrcode = 'qrcodes/' . md5($version->version) . '.png';

        if (!Storage::disk('public')->exists($file_qrcode)) {
            Storage::disk('public')->put(
                $file_qrcode,
                QrCode::format('png')->size(224)
                    ->generate($file)
            );
        }
        $qrcode = storage_url($file_qrcode);
        $file_ios = 'https://www.pgyer.com/LVuc';
        return view('share.down', compact(['file','qrcode','file_ios']));
    }

    public function register(Request $request)
    {
        $url = env('APP_URL');
        $invitation_code = $request->input('code');
        return view('share.register', compact(['url','invitation_code']));
    }

    /**
     * 实名认证
     */
    public function authentication(AuthenticationRequest $request)
    {
        $user = $this->getUser();
        $verifyData = \Cache::get($request->verification_key);
        if (!$verifyData) {
            return $this->fail(Code::PARAMETER_ERROR, '验证码已失效');
        }

        if (!hash_equals($verifyData['code'], $request->verification_code)) {
            return $this->fail(Code::PARAMETER_ERROR, '验证码错误');
        }
        $user->id_card = $request->card;
        $user->real_name = $request->real_name;
        $user->phone = $verifyData['phone'];
        $user->save();
        \Cache::forget($request->verification_key);
        return $this->fail(Code::PARAMETER_ERROR, '实名认证成功');
    }
    /**
     * 短信验证
     */
    public function sms(VerificationCodeRequest $request, EasySms $easySms)
    {
        $phone = $request->phone;
        $code = str_pad(random_int(1, 999999), 6, 0, STR_PAD_LEFT);
        if (!app()->environment('production')) {
            $code = '123456';
        } else {
            try {
                $easySms->send($phone, [
                    'template' => 'SMS_1',
                    'data' => [
                        'code' => $code
                    ],
                ]);
            } catch (\GuzzleHttp\Exception\ClientException $exception) {
                $response = $exception->getResponse();
                $result = json_decode($response->getBody()->getContents(), true);
                return $this->fail(Code::PARAMETER_ERROR, $result['msg']??'短信发送异常');
            }
        }


        $key = 'verificationCode_'.str_random(15);
        $expiredAt = now()->addMinutes(10);
        // 缓存验证码 10分钟过期
        \Cache::put($key, ['phone' => $phone, 'code' => $code], $expiredAt);

        return $this->success([
            'key' => $key,
            'expired_at' => $expiredAt->toDateTimeString(),
        ]);
    }
}
